#include <string.h>
#include <memory>
#include <thread>
#include <functional>
#include <stdio.h>
#include <iostream>
#include <unistd.h>

/*
 * 线程分离
 */

/*
 * 父进程需要阻塞式等待子进程退出，主线程等该次线程时也是阻塞式等待，父进程可以设置为 WNOHANG，变成轮询式等待，
 * 避免自己一直处于阻塞；次线程该如何做才能避免等待时阻塞呢？
 *
 * 答案是 分离 Detach
 *
 * 线程在被创建时，默认属性都是 joinable 的，即主线程需要使用 pthread_join 来等待次线程退出，并对其进行资源释放；
 * 实际上我们可以把这一操作留给系统自动处理，如此一来主线程就可以不必等待次线程，也就可以避免等待时阻塞了，
 * 这一操作叫做 线程分离.
 *
 * 线程分离的本质是将 joinable 属性修改为 detach，告诉系统线程退出后资源自动释放.
 *
 * 注意: 如果线程失去了 joinable 属性，就无法被 join，如果 join 就会报错.
 */

using namespace std;


void *threadRun(void *arg)
{
    int n = 3;
    while(n)
    {
        cout << "次线程 " << n-- << endl;
        sleep(1);
    }

    return NULL;
}

int main()
{
    pthread_t t;
    pthread_create(&t, nullptr, threadRun, nullptr);

    pthread_detach(t);  /* 主线程可以不用等待次线程，两个执行流并发运行，并且不必担心次线程出现僵尸问题 */

    int n = 5;
    while(n)
    {
        cout << "主线程 " << n-- << endl;
        sleep(1);
    }

    return 0;
}

/*
 * 建议将 pthread_detach 放在待分离线程的 线程创建(pthread_create) 语句之后，
 * 如果放在线程执行函数中，可能会因为调度优先级问题引发错误(未知结果).
 *
 * 线程被创建后，谁先执行不确定
 *
 * 总之，线程被分离后，主线程就可以不必关心了，即不需要 join 等待，是否分离线程取决于具体的应用场景
 */

